/*-
 * Copyright (c) 2012 Diamond Light Source Ltd.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */

package org.eclipse.dawnsci.analysis.dataset;

import static org.junit.Assert.assertEquals;

import org.eclipse.dawnsci.analysis.dataset.impl.FFT;
import org.eclipse.january.asserts.TestUtils;
import org.eclipse.january.dataset.Dataset;
import org.eclipse.january.dataset.DatasetFactory;
import org.eclipse.january.dataset.DoubleDataset;
import org.eclipse.january.dataset.IndexIterator;
import org.junit.Test;

//TODO truncate tests

/**
 * Test fast Fourier transform routine
 */
public class FFTTest {

	private static double fabstol = 1e-4;
	private static double dabstol = 1e-8;

	@Test
	public void test1D() {
		testfft1d(Dataset.FLOAT32);
		testfft1d(Dataset.FLOAT64);
	}

	private void testfft1d(int dtype) {
		double abstol = 0;
		switch (dtype) {
		case Dataset.FLOAT32:
			abstol = fabstol;
			break;
		case Dataset.FLOAT64:
			abstol = dabstol;
			break;
		}

		double[] or = { 66., -6., -6., -6., -6., -6., -6., -6., -6., -6., -6., -6. };
		double[] oi = { 0., 22.39230485, 10.39230485, 6., 3.46410162, 1.60769515, 0., -1.60769515, -3.46410162, -6.,
				-10.39230485, -22.39230485 };
		int i;
		Dataset a, f, g;
		IndexIterator it;

		a = DatasetFactory.createRange(12, dtype);
		f = FFT.fft(a);
		i = 0;
		it = f.getIterator();
		while (it.hasNext()) {
			assertEquals("1D double: real", or[i], f.getElementDoubleAbs(it.index), abstol);
			assertEquals("1D double: imag", oi[i], f.getElementDoubleAbs(it.index+1), abstol);
			i++;
		}

		g = FFT.ifft(f);
		i = 0;
		it = g.getIterator();
		while (it.hasNext()) {
			assertEquals("1D double: real", i, g.getElementDoubleAbs(it.index), abstol);
			assertEquals("1D double: imag", 0, g.getElementDoubleAbs(it.index + 1), abstol);
			i++;
		}

		or = new double[] {5.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5};
		oi = new double[] {0, -1.86602540378, -0.866025403784, -0.5, -0.288675134595, -0.133974596216,
				0.0, 0.133974596216, 0.288675134595, 0.5, 0.866025403784, 1.86602540378};
		g = FFT.ifft(a);
		i = 0;
		it = g.getIterator();
		while (it.hasNext()) {
			assertEquals("1D double: real", or[i], g.getElementDoubleAbs(it.index), abstol);
			assertEquals("1D double: imag", oi[i], g.getElementDoubleAbs(it.index + 1), abstol);
			i++;
		}

		double[] br = { 6., -2., -2., -2., 22., -2., -2., -2., 38., -2., -2., -2. };
		double[] bi = { 0., 2., 0., -2., 0., 2., 0., -2., 0., 2., 0., -2. };
		a.setShape(3, 4);
		f = FFT.fft(a);
		assertEquals("1D double: rank", 2, f.getRank());
		assertEquals("1D double: shape", 3, f.getShape()[0]);
		assertEquals("1D double: shape", 4, f.getShape()[1]);
		i = 0;
		it = f.getIterator();
		while (it.hasNext()) {
			assertEquals("1D double: real", br[i], f.getElementDoubleAbs(it.index), abstol);
			assertEquals("1D double: imag", bi[i], f.getElementDoubleAbs(it.index+1), abstol);
			i++;
		}

		g = FFT.ifft(f);
		i = 0;
		it = g.getIterator();
		while (it.hasNext()) {
			assertEquals("1D double: real", i, g.getElementDoubleAbs(it.index), abstol);
			assertEquals("1D double: imag", 0, g.getElementDoubleAbs(it.index + 1), abstol);
			i++;
		}

		double[] ar = { 12., 15., 18., 21., -6., -6., -6., -6., -6., -6., -6., -6. };
		double[] ai = { 0., 0., 0., 0., 3.46410162, 3.46410162, 3.46410162, 3.46410162, -3.46410162, -3.46410162,
				-3.46410162, -3.46410162 };
		f = FFT.fft(a, a.getShape()[0], 0);
		assertEquals("1D double: rank", 2, f.getRank());
		assertEquals("1D double: shape", 3, f.getShape()[0]);
		assertEquals("1D double: shape", 4, f.getShape()[1]);
		i = 0;
		it = f.getIterator();
		while (it.hasNext()) {
			assertEquals("1D double: real", ar[i], f.getElementDoubleAbs(it.index), abstol);
			assertEquals("1D double: imag", ai[i], f.getElementDoubleAbs(it.index+1), abstol);
			i++;
		}

		g = FFT.ifft(f, f.getShape()[0], 0);
		i = 0;
		it = g.getIterator();
		while (it.hasNext()) {
			assertEquals("1D double: real", i, g.getElementDoubleAbs(it.index), abstol);
			assertEquals("1D double: imag", 0, g.getElementDoubleAbs(it.index + 1), abstol);
			i++;
		}

		f = FFT.fft(a, a.getShape()[1], 1);
		assertEquals("1D double: rank", 2, f.getRank());
		assertEquals("1D double: shape", 3, f.getShape()[0]);
		assertEquals("1D double: shape", 4, f.getShape()[1]);
		i = 0;
		it = f.getIterator();
		while (it.hasNext()) {
			assertEquals("1D double: real", br[i], f.getElementDoubleAbs(it.index), abstol);
			assertEquals("1D double: imag", bi[i], f.getElementDoubleAbs(it.index+1), abstol);
			i++;
		}

		g = FFT.ifft(f, f.getShape()[1], 1);
		i = 0;
		it = g.getIterator();
		while (it.hasNext()) {
			assertEquals("1D double: real", i, g.getElementDoubleAbs(it.index), abstol);
			assertEquals("1D double: imag", 0, g.getElementDoubleAbs(it.index + 1), abstol);
			i++;
		}

		// expanded FFT
		a.setShape(12);
		double[] cr = { 66., -32.69653822, -5.80075453, 8.39918694, 2.97111336, -6., -3.89918694, 4.02617939,
				4.02617939, -3.89918694, -6., 2.97111336, 8.39918694, -5.80075453, -32.69653822 };
		double[] ci = { 0., 8.51685189, -13.54095942, -3.57971208, 6.94525397, 3.46410162, -4.84103929, -3.88832857,
				3.88832857, 4.84103929, -3.46410162, -6.94525397, 3.57971208, 13.54095942, -8.51685189 };
		f = FFT.fft(a, 15, -1);
		assertEquals("1D double: shape", 15, f.getShape()[0]);
		i = 0;
		it = f.getIterator();
		while (it.hasNext()) {
			assertEquals("1D double: real", cr[i], f.getElementDoubleAbs(it.index), abstol);
			assertEquals("1D double: imag", ci[i], f.getElementDoubleAbs(it.index+1), abstol);
			i++;
		}

		g = FFT.ifft(f);
		i = 0;
		it = g.getIterator();
		while (it.hasNext()) {
			assertEquals("1D double: real", i < 12 ? i : 0, g.getElementDoubleAbs(it.index), abstol);
			assertEquals("1D double: imag", 0, g.getElementDoubleAbs(it.index + 1), abstol);
			i++;
		}

		double[] dr = { 12., 15., 18., 21., -5.23606798, -4.73606798, -4.23606798, -3.73606798, -0.76393202,
				-0.26393202, 0.23606798, 0.73606798, -0.76393202, -0.26393202, 0.23606798, 0.73606798, -5.23606798,
				-4.73606798, -4.23606798, -3.73606798 };
		double[] di = { 0., 0., 0., 0., -8.50650808, -10.04534985, -11.58419162, -13.12303339, 5.25731112, 5.62058239,
				5.98385365, 6.34712491, -5.25731112, -5.62058239, -5.98385365, -6.34712491, 8.50650808, 10.04534985,
				11.58419162, 13.12303339 };
		a.setShape(3, 4);
		f = FFT.fft(a, 5, 0);
		assertEquals("1D double: rank", 2, f.getRank());
		assertEquals("1D double: shape", 5, f.getShape()[0]);
		assertEquals("1D double: shape", 4, f.getShape()[1]);
		i = 0;
		it = f.getIterator();
		while (it.hasNext()) {
			assertEquals("1D double: real", dr[i], f.getElementDoubleAbs(it.index), abstol);
			assertEquals("1D double: imag", di[i], f.getElementDoubleAbs(it.index+1), abstol);
			i++;
		}

		g = FFT.ifft(f, f.getShape()[0], 0);
		i = 0;
		it = g.getIterator();
		while (it.hasNext()) {
			assertEquals("1D double: real", i < 12 ? i : 0, g.getElementDoubleAbs(it.index), abstol);
			assertEquals("1D double: imag", 0, g.getElementDoubleAbs(it.index + 1), abstol);
			i++;
		}
	}

	@Test
	public void test2D() {
		testfft2d(Dataset.FLOAT32);
		testfft2d(Dataset.FLOAT64);
	}

	private void testfft2d(int dtype) {
		double abstol = 0;
		switch (dtype) {
		case Dataset.FLOAT32:
			abstol = fabstol;
			break;
		case Dataset.FLOAT64:
			abstol = dabstol;
			break;
		}

		int i;
		Dataset a, f, g;
		IndexIterator it;

		double[] ar = { 66., -6., -6., -6., -24., 0., 0., 0., -24., 0., 0., 0. };
		double[] ai = { 0., 6., 0., -6., 13.85640646, 0., 0., 0., -13.85640646, 0., 0., 0. };
		a = DatasetFactory.createRange(12, dtype);
		a.setShape(3, 4);
		f = FFT.fft2(a, null, null);
		assertEquals("2D double: rank", 2, f.getRank());
		assertEquals("2D double: shape", 3, f.getShape()[0]);
		assertEquals("2D double: shape", 4, f.getShape()[1]);
		i = 0;
		it = f.getIterator();
		while (it.hasNext()) {
			assertEquals("2D double: real", ar[i], f.getElementDoubleAbs(it.index), abstol);
			assertEquals("2D double: imag", ai[i], f.getElementDoubleAbs(it.index+1), abstol);
			i++;
		}

		g = FFT.ifft2(f, null, null);
		i = 0;
		it = g.getIterator();
		while (it.hasNext()) {
			assertEquals("2D double: real", i, g.getElementDoubleAbs(it.index), abstol);
			assertEquals("2D double: imag", 0, g.getElementDoubleAbs(it.index+1), abstol);
			i++;
		}

		ar = new double[] {5.5, -0.5, -0.5, -0.5, -2, 0, 0, 0, -2, 0, 0, 0};
		ai = new double[] {0, -0.5, 0, 0.5, -1.15470053838, 0, 0, 0, 1.15470053838, 0, 0, 0};
		g = FFT.ifft2(a, null, null);
		i = 0;
		it = g.getIterator();
		while (it.hasNext()) {
			assertEquals("2D double: real", ar[i], g.getElementDoubleAbs(it.index), abstol);
			assertEquals("2D double: imag", ai[i], g.getElementDoubleAbs(it.index + 1), abstol);
			i++;
		}

		double[] br = { 190., -10., -10., -10., -40., 0., 0., 0., -40., 0., 0., 0., -40., 0., 0., 0., -40., 0., 0., 0.,
				590., -10., -10., -10., -40., 0., 0., 0., -40., 0., 0., 0., -40., 0., 0., 0., -40., 0., 0., 0., 990.,
				-10., -10., -10., -40., 0., 0., 0., -40., 0., 0., 0., -40., 0., 0., 0., -40., 0., 0., 0. };
		double[] bi = { 0., 10., 0., -10., 55.05527682, 0., 0., 0., 12.99678785, 0., 0., 0., -12.99678785, 0., 0., 0.,
				-55.05527682, 0., 0., 0., 0., 10., 0., -10., 55.05527682, 0., 0., 0., 12.99678785, 0., 0., 0.,
				-12.99678785, 0., 0., 0., -55.05527682, 0., 0., 0., 0., 10., 0., -10., 55.05527682, 0., 0., 0.,
				12.99678785, 0., 0., 0., -12.99678785, 0., 0., 0., -55.05527682, 0., 0., 0. };

		a = DatasetFactory.createRange(60, Dataset.FLOAT64);
		a.setShape(3, 5, 4);
		f = FFT.fft2(a, null, null);
		assertEquals("2D double: rank", 3, f.getRank());
		assertEquals("2D double: shape", 3, f.getShape()[0]);
		assertEquals("2D double: shape", 5, f.getShape()[1]);
		assertEquals("2D double: shape", 4, f.getShape()[2]);
		i = 0;
		it = f.getIterator();
		while (it.hasNext()) {
			assertEquals("2D double: real", br[i], f.getElementDoubleAbs(it.index), abstol);
			assertEquals("2D double: imag", bi[i], f.getElementDoubleAbs(it.index+1), abstol);
			i++;
		}

		g = FFT.ifft2(f, null, null);
		i = 0;
		it = g.getIterator();
		while (it.hasNext()) {
			assertEquals("2D double: real", i, g.getElementDoubleAbs(it.index), abstol);
			assertEquals("2D double: imag", 0, g.getElementDoubleAbs(it.index+1), abstol);
			i++;
		}

		double[] cr = { 258., -6., -6., -6., 306., -6., -6., -6., 354., -6., -6., -6., 402., -6., -6., -6., 450., -6.,
				-6., -6., -120., 0., 0., 0., -120., 0., 0., 0., -120., 0., 0., 0., -120., 0., 0., 0., -120., 0., 0.,
				0., -120., 0., 0., 0., -120., 0., 0., 0., -120., 0., 0., 0., -120., 0., 0., 0., -120., 0., 0., 0. };
		double[] ci = { 0., 6., 0., -6., 0., 6., 0., -6., 0., 6., 0., -6., 0., 6., 0., -6., 0., 6., 0., -6.,
				69.2820323, 0., 0., 0., 69.2820323, 0., 0., 0., 69.2820323, 0., 0., 0., 69.2820323, 0., 0., 0.,
				69.2820323, 0., 0., 0., -69.2820323, 0., 0., 0., -69.2820323, 0., 0., 0., -69.2820323, 0., 0., 0.,
				-69.2820323, 0., 0., 0., -69.2820323, 0., 0., 0. };
		f = FFT.fft2(a, null, new int[] { 0, 2 });
		assertEquals("2D double: rank", 3, f.getRank());
		assertEquals("2D double: shape", 3, f.getShape()[0]);
		assertEquals("2D double: shape", 5, f.getShape()[1]);
		assertEquals("2D double: shape", 4, f.getShape()[2]);
		i = 0;
		it = f.getIterator();
		while (it.hasNext()) {
			assertEquals("2D double: real", cr[i], f.getElementDoubleAbs(it.index), abstol);
			assertEquals("2D double: imag", ci[i], f.getElementDoubleAbs(it.index+1), abstol);
			i++;
		}

		FFT.fft2(a, null, new int[] { -2, -1 });

		g = FFT.ifft2(f, null, new int[] { 0, 2 });
		i = 0;
		it = g.getIterator();
		while (it.hasNext()) {
			assertEquals("2D double: real", i, g.getElementDoubleAbs(it.index), abstol);
			assertEquals("2D double: imag", 0, g.getElementDoubleAbs(it.index+1), abstol);
			i++;
		}

		double[] dr = { 258., -29.74922359, 50.74922359, 50.74922359, -29.74922359, 306., -33.45742753, 60.45742753,
				60.45742753, -33.45742753, 354., -37.16563146, 70.16563146, 70.16563146, -37.16563146, 402.,
				-40.87383539, 79.87383539, 79.87383539, -40.87383539, 450., -44.58203932, 89.58203932, 89.58203932,
				-44.58203932, 22.68164792, -58.93494429, -30.89772845, 38.73484154, 46.26097667, 45.09714981,
				-67.34974692, -30.49448701, 47.39886108, 51.21239379, 67.5126517, -75.76454956, -30.09124558,
				56.06288063, 56.16381092, 89.92815358, -84.17935219, -29.68800414, 64.72690018, 61.11522804,
				112.34365547, -92.59415483, -29.28476271, 73.39091972, 66.06664517, -162.69763239, 10.73835058,
				-34.93965408, -30.75499843, 15.20806734, -164.67346922, 8.83273803, -36.61134662, -29.88254868,
				17.41896348, -166.64930605, 6.92712547, -38.28303915, -29.01009893, 19.62985961, -168.62514288,
				5.02151291, -39.95473169, -28.13764918, 21.84075575, -170.60097971, 3.11590036, -41.62642423,
				-27.26519943, 24.05165188, 32.01598447, 16.77822603, 19.9471837, -7.68639203, -26.45392859,
				43.57631941, 17.20881292, 23.10338477, -6.16633938, -28.67068545, 55.13665436, 17.6393998, 26.25958583,
				-4.64628674, -30.88744232, 66.6969893, 18.06998669, 29.4157869, -3.12623409, -33.10419918, 78.25732424,
				18.50057357, 32.57198796, -1.60618144, -35.32095604, 32.01598447, -26.45392859, -7.68639203,
				19.9471837, 16.77822603, 43.57631941, -28.67068545, -6.16633938, 23.10338477, 17.20881292, 55.13665436,
				-30.88744232, -4.64628674, 26.25958583, 17.6393998, 66.6969893, -33.10419918, -3.12623409, 29.4157869,
				18.06998669, 78.25732424, -35.32095604, -1.60618144, 32.57198796, 18.50057357, -162.69763239,
				15.20806734, -30.75499843, -34.93965408, 10.73835058, -164.67346922, 17.41896348, -29.88254868,
				-36.61134662, 8.83273803, -166.64930605, 19.62985961, -29.01009893, -38.28303915, 6.92712547,
				-168.62514288, 21.84075575, -28.13764918, -39.95473169, 5.02151291, -170.60097971, 24.05165188,
				-27.26519943, -41.62642423, 3.11590036, 22.68164792, 46.26097667, 38.73484154, -30.89772845,
				-58.93494429, 45.09714981, 51.21239379, 47.39886108, -30.49448701, -67.34974692, 67.5126517,
				56.16381092, 56.06288063, -30.09124558, -75.76454956, 89.92815358, 61.11522804, 64.72690018,
				-29.68800414, -84.17935219, 112.34365547, 66.06664517, 73.39091972, -29.28476271, -92.59415483 };
		double[] di = { 0., -58.15320477, -39.88364044, 39.88364044, 58.15320477, 0., -69.56588297, -46.93706347,
				46.93706347, 69.56588297, 0., -80.97856116, -53.9904865, 53.9904865, 80.97856116, 0., -92.39123936,
				-61.04390953, 61.04390953, 92.39123936, 0., -103.80391755, -68.09733255, 68.09733255, 103.80391755,
				-229.07554091, 19.5429154, -49.74637411, -41.23907274, 27.34934168, -257.18369123, 16.38478715,
				-58.72524229, -43.6301902, 34.850418, -285.29184154, 13.2266589, -67.70411047, -46.02130766,
				42.35149431, -313.39999186, 10.06853065, -76.68297865, -48.41242513, 49.85257063, -341.50814217,
				6.91040239, -85.66184683, -50.80354259, 57.35364694, -11.81909975, 41.23601821, 21.85683273,
				-26.1211078, -35.86868678, -20.47580652, 42.37456871, 20.39631894, -28.16230546, -35.66970253,
				-29.13251329, 43.51311921, 18.93580516, -30.20350312, -35.47071827, -37.78922006, 44.65166971,
				17.47529137, -32.24470078, -35.27173402, -46.44592683, 45.79022021, 16.01477759, -34.28589844,
				-35.07274976, 92.47002453, -15.12636243, 13.35687952, 23.71577061, -1.43838964, 98.03718842,
				-18.30508246, 12.78411347, 26.54050176, 0.88015626, 103.60435231, -21.48380249, 12.21134742,
				29.3652329, 3.19870217, 109.17151621, -24.66252253, 11.63858138, 32.18996405, 5.51724808, 114.7386801,
				-27.84124256, 11.06581533, 35.0146952, 7.83579398, -92.47002453, 1.43838964, -23.71577061,
				-13.35687952, 15.12636243, -98.03718842, -0.88015626, -26.54050176, -12.78411347, 18.30508246,
				-103.60435231, -3.19870217, -29.3652329, -12.21134742, 21.48380249, -109.17151621, -5.51724808,
				-32.18996405, -11.63858138, 24.66252253, -114.7386801, -7.83579398, -35.0146952, -11.06581533,
				27.84124256, 11.81909975, 35.86868678, 26.1211078, -21.85683273, -41.23601821, 20.47580652,
				35.66970253, 28.16230546, -20.39631894, -42.37456871, 29.13251329, 35.47071827, 30.20350312,
				-18.93580516, -43.51311921, 37.78922006, 35.27173402, 32.24470078, -17.47529137, -44.65166971,
				46.44592683, 35.07274976, 34.28589844, -16.01477759, -45.79022021, 229.07554091, -27.34934168,
				41.23907274, 49.74637411, -19.5429154, 257.18369123, -34.850418, 43.6301902, 58.72524229, -16.38478715,
				285.29184154, -42.35149431, 46.02130766, 67.70411047, -13.2266589, 313.39999186, -49.85257063,
				48.41242513, 76.68297865, -10.06853065, 341.50814217, -57.35364694, 50.80354259, 85.66184683,
				-6.91040239 };
		f = FFT.fft2(a, new int[] { 7, 5 }, new int[] { 0, 2 });
		assertEquals("2D double: rank", 3, f.getRank());
		assertEquals("2D double: shape", 7, f.getShape()[0]);
		assertEquals("2D double: shape", 5, f.getShape()[1]);
		assertEquals("2D double: shape", 5, f.getShape()[2]);
		i = 0;
		it = f.getIterator();
		while (it.hasNext()) {
			assertEquals("2D double: real", dr[i], f.getElementDoubleAbs(it.index), abstol);
			assertEquals("2D double: imag", di[i], f.getElementDoubleAbs(it.index+1), abstol);
			i++;
		}

		g = FFT.ifft2(f, null, new int[] { 0, 2 });
		i = 0;
		it = g.getSliceIterator(null, a.getShape(), null);
		while (it.hasNext()) {
			assertEquals("2D double: real", i, g.getElementDoubleAbs(it.index), abstol);
			assertEquals("2D double: imag", 0, g.getElementDoubleAbs(it.index+1), abstol);
			i++;
		}
	}

	@Test
	public void test3D() {
		testfft3d(Dataset.FLOAT32);
		testfft3d(Dataset.FLOAT64);
	}

	private void testfft3d(int dtype) {
		double abstol = 0;
		switch (dtype) {
		case Dataset.FLOAT32:
			abstol = fabstol;
			break;
		case Dataset.FLOAT64:
			abstol = dabstol;
			break;
		}

		int i;
		Dataset a, f, g;
		IndexIterator it;

		double[] ar = { 1.77000000e+03, -3.00000000e+01, -3.00000000e+01, -3.00000000e+01, -1.20000000e+02,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.20000000e+02, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, -1.20000000e+02, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.20000000e+02,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -6.00000000e+02, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, -1.42108547e-14, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -7.10542736e-15,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -7.10542736e-15, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, -1.42108547e-14, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -6.00000000e+02,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.42108547e-14, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, -7.10542736e-15, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -7.10542736e-15,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.42108547e-14, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00 };
		double[] ai = { 0.00000000e+00, 3.00000000e+01, 0.00000000e+00, -3.00000000e+01, 1.65165830e+02,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 3.89903635e+01, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, -3.89903635e+01, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.65165830e+02,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 3.46410162e+02, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, -2.46139224e-14, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.23069612e-14,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.23069612e-14, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, -2.46139224e-14, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -3.46410162e+02,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 2.46139224e-14, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, 1.23069612e-14, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 1.23069612e-14,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 2.46139224e-14, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00 };

		a = DatasetFactory.createRange(60, Dataset.FLOAT64);
		a.setShape(3, 5, 4);
		f = FFT.fftn(a, null, null);
		assertEquals("3D double: rank", 3, f.getRank());
		assertEquals("3D double: shape", 3, f.getShape()[0]);
		assertEquals("3D double: shape", 5, f.getShape()[1]);
		assertEquals("3D double: shape", 4, f.getShape()[2]);
		i = 0;
		it = f.getIterator();
		while (it.hasNext()) {
			assertEquals("3D double: real", ar[i], f.getElementDoubleAbs(it.index),  Math.max(abstol,abstol*Math.abs(ar[i])));
			assertEquals("3D double: imag", ai[i], f.getElementDoubleAbs(it.index+1), Math.max(abstol,abstol*Math.abs(ai[i])));
			i++;
		}

		g = FFT.ifftn(f, null, null);
		i = 0;
		it = g.getIterator();
		while (it.hasNext()) {
			assertEquals("3D double: real", i, g.getElementDoubleAbs(it.index), abstol);
			assertEquals("3D double: imag", 0, g.getElementDoubleAbs(it.index+1), abstol);
			i++;
		}

		ar = new double[] { 29.5, -0.5, -0.5, -0.5, -2, 0, 0, 0, -2, 0, 0, 0, -2, 0, 0, 0,
				-2, 0, 0, 0, -10, 0, 0, 0, -2.22044604925e-16, 0, 0, 0, -1.48029736617e-16,
				0, 0, 0, -1.48029736617e-16, 0, 0, 0, -2.22044604925e-16, 0, 0, 0,
				-10, 0, 0, 0, -2.22044604925e-16, 0, 0, 0, -1.48029736617e-16, 0, 0, 0,
				-1.48029736617e-16, 0, 0, 0, -2.22044604925e-16, 0, 0, 0 };
		ai = new double[] { 0, -0.5, 0, 0.5, -2.75276384094, 0, 0, 0, -0.649839392466, 0, 0, 0,
				0.649839392466, 0, 0, 0, 2.75276384094, 0, 0, 0, -5.7735026919, 0, 0, 0,
				3.84592537277e-16, 0, 0, 0, 1.92296268638e-16, 0, 0, 0, 1.92296268638e-16, 0, 0, 0,
				3.84592537277e-16, 0, 0, 0, 5.7735026919, 0, 0, 0, -3.84592537277e-16, 0, 0, 0,
				-1.92296268638e-16, 0, 0, 0, -1.92296268638e-16, 0, 0, 0, -3.84592537277e-16, 0, 0, 0 };
		g = FFT.ifftn(a, null, null);
		i = 0;
		it = g.getIterator();
		while (it.hasNext()) {
			assertEquals("3D double: real", ar[i], g.getElementDoubleAbs(it.index), abstol);
			assertEquals("3D double: imag", ai[i], g.getElementDoubleAbs(it.index + 1), abstol);
			i++;
		}

		double[] br = { 1.77000000e+03, -3.00000000e+01, -3.00000000e+01, -3.00000000e+01, -3.97610007e+02,
				1.29463696e+01, 2.40581321e+00, -8.13474316e+00, 4.02178926e+02, -3.49467377e+00, -6.74093881e+00,
				-9.98720385e+00, 1.34310805e+01, -3.75256086e+00, -1.66487440e+00, 4.22812064e-01, 1.34310805e+01,
				4.22812064e-01, -1.66487440e+00, -3.75256086e+00, 4.02178926e+02, -9.98720385e+00, -6.74093881e+00,
				-3.49467377e+00, -3.97610007e+02, -8.13474316e+00, 2.40581321e+00, 1.29463696e+01, -4.28606798e+02,
				1.03884177e+01, -5.00000000e+00, -2.03884177e+01, -3.79912881e+02, 6.33042245e+00, 5.80771834e+00,
				5.28501422e+00, -2.14494858e+02, 4.54046318e+00, 5.41672942e-01, -3.45711730e+00, 7.63113708e+01,
				-8.42307097e-01, -1.34835211e+00, -1.85439712e+00, -1.52148639e+02, 1.99533447e+00, 7.93393975e-01,
				-4.08546521e-01, 2.33685566e+01, 1.28049348e-01, -2.78865255e+00, -5.70535444e+00, 3.63433731e+02,
				-7.99659528e+00, -5.00578060e+00, -2.01496592e+00, 1.86067977e+01, -8.63271264e+00, -5.00000000e+00,
				-1.36728736e+00, 1.57797991e+02, 1.17268879e+00, -8.75391544e-01, -2.92347187e+00, 6.81599815e+01,
				-1.79180035e+00, -1.51658140e+00, -1.24136246e+00, -6.26772134e+01, -5.74228318e-01, -2.46802330e-02,
				5.24867852e-01, 3.64769092e+01, -3.83930498e-01, -5.30277899e-01, -6.76625300e-01, -5.83103170e+01,
				-2.08770549e+00, -7.30398201e-01, 6.26909093e-01, -2.46004632e+02, 2.11890820e-01, 1.67732928e+00,
				3.14276774e+00, 1.86067977e+01, -1.36728736e+00, -5.00000000e+00, -8.63271264e+00, -2.46004632e+02,
				3.14276774e+00, 1.67732928e+00, 2.11890820e-01, -5.83103170e+01, 6.26909093e-01, -7.30398201e-01,
				-2.08770549e+00, 3.64769092e+01, -6.76625300e-01, -5.30277899e-01, -3.83930498e-01, -6.26772134e+01,
				5.24867852e-01, -2.46802330e-02, -5.74228318e-01, 6.81599815e+01, -1.24136246e+00, -1.51658140e+00,
				-1.79180035e+00, 1.57797991e+02, -2.92347187e+00, -8.75391544e-01, 1.17268879e+00, -4.28606798e+02,
				-2.03884177e+01, -5.00000000e+00, 1.03884177e+01, 3.63433731e+02, -2.01496592e+00, -5.00578060e+00,
				-7.99659528e+00, 2.33685566e+01, -5.70535444e+00, -2.78865255e+00, 1.28049348e-01, -1.52148639e+02,
				-4.08546521e-01, 7.93393975e-01, 1.99533447e+00, 7.63113708e+01, -1.85439712e+00, -1.34835211e+00,
				-8.42307097e-01, -2.14494858e+02, -3.45711730e+00, 5.41672942e-01, 4.54046318e+00, -3.79912881e+02,
				5.28501422e+00, 5.80771834e+00, 6.33042245e+00 };
		double[] bi = { 0.00000000e+00, 3.00000000e+01, 0.00000000e+00, -3.00000000e+01, -5.63538495e+02,
				8.13474316e+00, 1.05405564e+01, 1.29463696e+01, -1.82261009e+02, 9.98720385e+00, 3.24626504e+00,
				-3.49467377e+00, 1.90796460e+02, -4.22812064e-01, -2.08768646e+00, -3.75256086e+00, -1.90796460e+02,
				3.75256086e+00, 2.08768646e+00, 4.22812064e-01, 1.82261009e+02, 3.49467377e+00, -3.24626504e+00,
				-9.98720385e+00, 5.63538495e+02, -1.29463696e+01, -1.05405564e+01, -8.13474316e+00, -1.14303074e+03,
				2.03884177e+01, 1.53884177e+01, 1.03884177e+01, 3.83125174e+02, -5.28501422e+00, 5.22704111e-01,
				6.33042245e+00, -2.11202422e+02, 3.45711730e+00, 3.99879024e+00, 4.54046318e+00, -3.84933445e+01,
				1.85439712e+00, 5.06045010e-01, -8.42307097e-01, -1.38122374e+00, 4.08546521e-01, 1.20194050e+00,
				1.99533447e+00, -3.07050049e+02, 5.70535444e+00, 2.91670189e+00, 1.28049348e-01, 6.24901235e+01,
				2.01496592e+00, -2.99081468e+00, -7.99659528e+00, 5.94752652e+02, 1.36728736e+00, -3.63271264e+00,
				-8.63271264e+00, -7.54660992e+01, 2.92347187e+00, 2.04808033e+00, 1.17268879e+00, 1.33711551e+02,
				1.24136246e+00, -2.75218948e-01, -1.79180035e+00, 3.53035690e+01, -5.24867852e-01, -5.49548085e-01,
				-5.74228318e-01, 1.01729052e+01, 6.76625300e-01, 1.46347401e-01, -3.83930498e-01, 1.34648848e+02,
				-6.26909093e-01, -1.35730729e+00, -2.08770549e+00, -8.18424760e+01, -3.14276774e+00, -1.46543846e+00,
				2.11890820e-01, -5.94752652e+02, 8.63271264e+00, 3.63271264e+00, -1.36728736e+00, 8.18424760e+01,
				-2.11890820e-01, 1.46543846e+00, 3.14276774e+00, -1.34648848e+02, 2.08770549e+00, 1.35730729e+00,
				6.26909093e-01, -1.01729052e+01, 3.83930498e-01, -1.46347401e-01, -6.76625300e-01, -3.53035690e+01,
				5.74228318e-01, 5.49548085e-01, 5.24867852e-01, -1.33711551e+02, 1.79180035e+00, 2.75218948e-01,
				-1.24136246e+00, 7.54660992e+01, -1.17268879e+00, -2.04808033e+00, -2.92347187e+00, 1.14303074e+03,
				-1.03884177e+01, -1.53884177e+01, -2.03884177e+01, -6.24901235e+01, 7.99659528e+00, 2.99081468e+00,
				-2.01496592e+00, 3.07050049e+02, -1.28049348e-01, -2.91670189e+00, -5.70535444e+00, 1.38122374e+00,
				-1.99533447e+00, -1.20194050e+00, -4.08546521e-01, 3.84933445e+01, 8.42307097e-01, -5.06045010e-01,
				-1.85439712e+00, 2.11202422e+02, -4.54046318e+00, -3.99879024e+00, -3.45711730e+00, -3.83125174e+02,
				-6.33042245e+00, -5.22704111e-01, 5.28501422e+00 };
		f = FFT.fftn(a, new int[] { 5, 7, 4 }, null);
		assertEquals("3D double: rank", 3, f.getRank());
		assertEquals("3D double: shape", 5, f.getShape()[0]);
		assertEquals("3D double: shape", 7, f.getShape()[1]);
		assertEquals("3D double: shape", 4, f.getShape()[2]);
		i = 0;
		it = f.getIterator();
		while (it.hasNext()) {
			assertEquals("3D double: real", br[i], f.getElementDoubleAbs(it.index),  Math.max(abstol,abstol*Math.abs(br[i])));
			assertEquals("3D double: imag", bi[i], f.getElementDoubleAbs(it.index+1), Math.max(abstol,abstol*Math.abs(bi[i])));
			i++;
		}

		g = FFT.ifftn(f, new int[] { 5, 7, 4 }, null);
		i = 0;
		it = g.getSliceIterator(null, a.getShape(), null);
		while (it.hasNext()) {
			assertEquals("3D double: real", i, g.getElementDoubleAbs(it.index), abstol);
			assertEquals("3D double: imag", 0, g.getElementDoubleAbs(it.index+1), abstol);
			i++;
		}

		double[] cr = { 1.77000000e+03, -3.00000000e+01, -3.00000000e+01, -3.00000000e+01, -1.20000000e+02,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.20000000e+02, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, -1.20000000e+02, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.20000000e+02,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -6.00000000e+02, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, -1.42108547e-14, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -7.10542736e-15,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -7.10542736e-15, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, -1.42108547e-14, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -6.00000000e+02,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.42108547e-14, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, -7.10542736e-15, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -7.10542736e-15,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.42108547e-14, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, 5.37000000e+03, -3.00000000e+01, -3.00000000e+01, -3.00000000e+01, -1.20000000e+02,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.20000000e+02, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, -1.20000000e+02, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.20000000e+02,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -6.00000000e+02, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.42108547e-14,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.42108547e-14, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -6.00000000e+02,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, -1.42108547e-14, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.42108547e-14,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00 };
		double[] ci = { 0.00000000e+00, 3.00000000e+01, 0.00000000e+00, -3.00000000e+01, 1.65165830e+02,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 3.89903635e+01, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, -3.89903635e+01, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.65165830e+02,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 3.46410162e+02, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, -2.46139224e-14, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.23069612e-14,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.23069612e-14, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, -2.46139224e-14, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -3.46410162e+02,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 2.46139224e-14, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, 1.23069612e-14, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 1.23069612e-14,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 2.46139224e-14, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, 0.00000000e+00, 3.00000000e+01, 0.00000000e+00, -3.00000000e+01, 1.65165830e+02,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 3.89903635e+01, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, -3.89903635e+01, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -1.65165830e+02,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 3.46410162e+02, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -2.46139224e-14,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -2.46139224e-14, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, -3.46410162e+02,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00, 2.46139224e-14, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 2.46139224e-14,
				0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
				0.00000000e+00 };
		Dataset b = DatasetFactory.createRange(120, Dataset.FLOAT64).reshape(2, 3, 5, 4);
		f = FFT.fftn(b, null, new int[] { -3, -2, -1 });
		assertEquals("3D double: rank", 4, f.getRank());
		assertEquals("3D double: shape", 2, f.getShape()[0]);
		assertEquals("3D double: shape", 3, f.getShape()[1]);
		assertEquals("3D double: shape", 5, f.getShape()[2]);
		assertEquals("3D double: shape", 4, f.getShape()[3]);
		i = 0;
		it = f.getIterator();
		while (it.hasNext()) {
			assertEquals("3D double: real", cr[i], f.getElementDoubleAbs(it.index),  Math.max(abstol,abstol*Math.abs(cr[i])));
			assertEquals("3D double: imag", ci[i], f.getElementDoubleAbs(it.index+1), Math.max(abstol,abstol*Math.abs(ci[i])));
			i++;
		}

		g = FFT.ifftn(f, null, new int[] { -3, -2, -1 });
		i = 0;
		it = g.getSliceIterator(null, b.getShape(), null);
		while (it.hasNext()) {
			assertEquals("3D double: real", i, g.getElementDoubleAbs(it.index), abstol);
			assertEquals("3D double: imag", 0, g.getElementDoubleAbs(it.index+1), abstol);
			i++;
		}

		double[] dr = { 1.77000000e+03, 1.72133120e+02, 2.07690161e+02, 2.05176719e+02, 2.05176719e+02, 2.07690161e+02,
				1.72133120e+02, -3.97610007e+02, -3.58329185e+02, -4.79748793e+00, -1.41247772e+02, 4.44232247e+01,
				-9.24301844e+01, 2.66804419e+02, 4.02178926e+02, -6.17943905e+01, 6.12439002e+01, 1.67052005e+01,
				7.66162641e+01, 3.32070950e+01, 1.40266197e+02, 1.34310805e+01, 1.04224984e+02, -1.25184243e+01,
				3.15852843e+01, -3.00115138e+01, 1.43711659e+01, -1.06318776e+02, 1.34310805e+01, -1.06318776e+02,
				1.43711659e+01, -3.00115138e+01, 3.15852843e+01, -1.25184243e+01, 1.04224984e+02, 4.02178926e+02,
				1.40266197e+02, 3.32070950e+01, 7.66162641e+01, 1.67052005e+01, 6.12439002e+01, -6.17943905e+01,
				-3.97610007e+02, 2.66804419e+02, -9.24301844e+01, 4.44232247e+01, -1.41247772e+02, -4.79748793e+00,
				-3.58329185e+02, -4.28606798e+02, -6.93505560e+02, 2.74142091e+01, -2.41994097e+02, 1.29484637e+02,
				-1.39085855e+02, 5.69981567e+02, -3.79912881e+02, 1.71646762e+02, -6.74363747e+01, 1.54521636e+01,
				-1.04207111e+02, -2.22917304e+01, -2.47607849e+02, -2.14494858e+02, -1.43086594e+02, -1.01001376e+01,
				-6.13351260e+01, 8.29184236e+00, -4.30339103e+01, 9.12365651e+01, 7.63113708e+01, -1.39390379e+01,
				1.17216126e+01, 2.56664929e+00, 1.50663639e+01, 6.13733425e+00, 2.86017573e+01, -1.52148639e+02,
				-1.89252035e+01, -1.74487117e+01, -1.93235481e+01, -1.78634488e+01, -1.98712285e+01, -1.65140205e+01,
				2.33685566e+01, -1.70893798e+02, 2.28816003e+01, -4.79478074e+01, 5.08017601e+01, -1.95603731e+01,
				1.67604610e+02, 3.63433731e+02, 7.25746238e+01, 3.65978148e+01, 5.38201330e+01, 3.16743453e+01,
				4.97354461e+01, 1.89258728e+00, 1.86067977e+01, 3.21219904e+02, -3.91459250e+01, 9.44236378e+01,
				-9.51296987e+01, 3.92776781e+01, -3.32940498e+02, 1.57797991e+02, -2.38036317e+01, 2.57941764e+01,
				6.55172074e+00, 3.19597493e+01, 1.28639767e+01, 6.03866960e+01, 6.81599815e+01, 7.93684246e+01,
				-4.72814160e-01, 2.87836644e+01, -1.33687650e+01, 1.61418362e+01, -6.72944123e+01, -6.26772134e+01,
				1.16646803e+01, -1.04867628e+01, -2.07941151e+00, -1.36163380e+01, -5.20485123e+00, -2.74147980e+01,
				3.64769092e+01, 9.20804026e+00, 3.84491250e+00, 5.80752649e+00, 2.74348043e+00, 4.79494927e+00,
				-1.82518603e+00, -5.83103170e+01, 6.57644825e+01, -1.69982959e+01, 1.40053527e+01, -2.93655916e+01,
				1.76044452e+00, -8.27337205e+01, -2.46004632e+02, -7.22787057e+01, -2.64412039e+01, -4.20541748e+01,
				-1.76496375e+01, -3.35436664e+01, 1.62698931e+01, 1.86067977e+01, -3.32940498e+02, 3.92776781e+01,
				-9.51296987e+01, 9.44236378e+01, -3.91459250e+01, 3.21219904e+02, -2.46004632e+02, 1.62698931e+01,
				-3.35436664e+01, -1.76496375e+01, -4.20541748e+01, -2.64412039e+01, -7.22787057e+01, -5.83103170e+01,
				-8.27337205e+01, 1.76044452e+00, -2.93655916e+01, 1.40053527e+01, -1.69982959e+01, 6.57644825e+01,
				3.64769092e+01, -1.82518603e+00, 4.79494927e+00, 2.74348043e+00, 5.80752649e+00, 3.84491250e+00,
				9.20804026e+00, -6.26772134e+01, -2.74147980e+01, -5.20485123e+00, -1.36163380e+01, -2.07941151e+00,
				-1.04867628e+01, 1.16646803e+01, 6.81599815e+01, -6.72944123e+01, 1.61418362e+01, -1.33687650e+01,
				2.87836644e+01, -4.72814160e-01, 7.93684246e+01, 1.57797991e+02, 6.03866960e+01, 1.28639767e+01,
				3.19597493e+01, 6.55172074e+00, 2.57941764e+01, -2.38036317e+01, -4.28606798e+02, 5.69981567e+02,
				-1.39085855e+02, 1.29484637e+02, -2.41994097e+02, 2.74142091e+01, -6.93505560e+02, 3.63433731e+02,
				1.89258728e+00, 4.97354461e+01, 3.16743453e+01, 5.38201330e+01, 3.65978148e+01, 7.25746238e+01,
				2.33685566e+01, 1.67604610e+02, -1.95603731e+01, 5.08017601e+01, -4.79478074e+01, 2.28816003e+01,
				-1.70893798e+02, -1.52148639e+02, -1.65140205e+01, -1.98712285e+01, -1.78634488e+01, -1.93235481e+01,
				-1.74487117e+01, -1.89252035e+01, 7.63113708e+01, 2.86017573e+01, 6.13733425e+00, 1.50663639e+01,
				2.56664929e+00, 1.17216126e+01, -1.39390379e+01, -2.14494858e+02, 9.12365651e+01, -4.30339103e+01,
				8.29184236e+00, -6.13351260e+01, -1.01001376e+01, -1.43086594e+02, -3.79912881e+02, -2.47607849e+02,
				-2.22917304e+01, -1.04207111e+02, 1.54521636e+01, -6.74363747e+01, 1.71646762e+02, 5.37000000e+03,
				6.22133120e+02, 6.57690161e+02, 6.55176719e+02, 6.55176719e+02, 6.57690161e+02, 6.22133120e+02,
				-6.86307592e+02, -1.08713431e+03, 3.52562802e+01, -3.75596565e+02, 2.06597621e+02, -2.04658349e+02,
				9.23435144e+02, 1.21109158e+03, -1.74022555e+02, 1.85807765e+02, 5.67589686e+01, 2.38790660e+02,
				1.10871394e+02, 4.54722525e+02, 2.13216008e+02, 2.66399380e+02, -2.62596053e+00, 9.58265405e+01,
				-4.43065381e+01, 5.44249340e+01, -2.18546941e+02, 2.13216008e+02, -2.18546941e+02, 5.44249340e+01,
				-4.43065381e+01, 9.58265405e+01, -2.62596053e+00, 2.66399380e+02, 1.21109158e+03, 4.54722525e+02,
				1.10871394e+02, 2.38790660e+02, 5.67589686e+01, 1.85807765e+02, -1.74022555e+02, -6.86307592e+02,
				9.23435144e+02, -2.04658349e+02, 2.06597621e+02, -3.75596565e+02, 3.52562802e+01, -1.08713431e+03,
				1.71393202e+02, -1.62982151e+03, 2.13574280e+02, -4.56441079e+02, 4.93931619e+02, -1.75245926e+02,
				1.65629751e+03, -1.07683908e+03, 5.01792421e+01, -1.50776334e+02, -8.14953648e+01, -1.81491133e+02,
				-1.13183321e+02, -3.00371879e+02, -2.79495611e+02, -4.14009360e+02, 1.06605066e+01, -1.44675086e+02,
				7.53816136e+01, -8.00447428e+01, 3.45909143e+02, 2.38113624e+02, -2.69706771e+01, 3.56023707e+01,
				1.32735253e+01, 4.48100511e+01, 2.27071394e+01, 8.20839598e+01, -2.47355916e+02, -1.09816794e+02,
				-2.06672608e+01, -5.38322434e+01, -7.15657276e+00, -4.04544987e+01, 5.05757508e+01, 3.58006862e+02,
				-3.20747599e+02, 8.57805326e+01, -6.09794466e+01, 1.47492976e+02, 1.20027102e+00, 4.01117987e+02,
				9.64127403e+02, 3.44215562e+02, 9.00800172e+01, 1.85162287e+02, 5.05056095e+01, 1.46426662e+02,
				-1.19574933e+02, 6.18606798e+02, 6.34959214e+02, 9.61274195e+00, 2.37752801e+02, -8.84588623e+01,
				1.40519011e+02, -4.96679808e+02, 2.62844976e+02, -1.45271152e+02, 5.37196022e+01, -1.88405786e+01,
				8.36137950e+01, 1.12002973e+01, 2.08115962e+02, 2.50149750e+02, 1.20204341e+02, 2.02878300e+01,
				5.67090901e+01, 4.20325139e+00, 4.08786342e+01, -6.26328862e+01, -5.97155854e+01, 4.81507960e+01,
				-1.40862854e+01, 8.62746453e+00, -2.35828070e+01, -8.64921584e-01, -6.31605068e+01, 1.00110257e+02,
				7.54436086e+00, 1.28562389e+01, 1.10089874e+01, 1.34503565e+01, 1.16919598e+01, 1.57468303e+01,
				2.93374671e+01, 1.65921733e+02, -1.58469940e+01, 5.04914683e+01, -4.39397613e+01, 2.25210887e+01,
				-1.60979025e+02, -4.47284146e+02, -1.13106387e+00, -6.21869126e+01, -3.96500885e+01, -7.03736023e+01,
				-4.81178361e+01, -1.05197627e+02, 6.18606798e+02, -4.96679808e+02, 1.40519011e+02, -8.84588623e+01,
				2.37752801e+02, 9.61274195e+00, 6.34959214e+02, -4.47284146e+02, -1.05197627e+02, -4.81178361e+01,
				-7.03736023e+01, -3.96500885e+01, -6.21869126e+01, -1.13106387e+00, 2.93374671e+01, -1.60979025e+02,
				2.25210887e+01, -4.39397613e+01, 5.04914683e+01, -1.58469940e+01, 1.65921733e+02, 1.00110257e+02,
				1.57468303e+01, 1.16919598e+01, 1.34503565e+01, 1.10089874e+01, 1.28562389e+01, 7.54436086e+00,
				-5.97155854e+01, -6.31605068e+01, -8.64921584e-01, -2.35828070e+01, 8.62746453e+00, -1.40862854e+01,
				4.81507960e+01, 2.50149750e+02, -6.26328862e+01, 4.08786342e+01, 4.20325139e+00, 5.67090901e+01,
				2.02878300e+01, 1.20204341e+02, 2.62844976e+02, 2.08115962e+02, 1.12002973e+01, 8.36137950e+01,
				-1.88405786e+01, 5.37196022e+01, -1.45271152e+02, 1.71393202e+02, 1.65629751e+03, -1.75245926e+02,
				4.93931619e+02, -4.56441079e+02, 2.13574280e+02, -1.62982151e+03, 9.64127403e+02, -1.19574933e+02,
				1.46426662e+02, 5.05056095e+01, 1.85162287e+02, 9.00800172e+01, 3.44215562e+02, 3.58006862e+02,
				4.01117987e+02, 1.20027102e+00, 1.47492976e+02, -6.09794466e+01, 8.57805326e+01, -3.20747599e+02,
				-2.47355916e+02, 5.05757508e+01, -4.04544987e+01, -7.15657276e+00, -5.38322434e+01, -2.06672608e+01,
				-1.09816794e+02, 2.38113624e+02, 8.20839598e+01, 2.27071394e+01, 4.48100511e+01, 1.32735253e+01,
				3.56023707e+01, -2.69706771e+01, -2.79495611e+02, 3.45909143e+02, -8.00447428e+01, 7.53816136e+01,
				-1.44675086e+02, 1.06605066e+01, -4.14009360e+02, -1.07683908e+03, -3.00371879e+02, -1.13183321e+02,
				-1.81491133e+02, -8.14953648e+01, -1.50776334e+02, 5.01792421e+01 };
		double[] di = { 0.00000000e+00, -9.80570194e+02, 1.34705680e+02, -2.90256739e+02, 2.90256739e+02,
				-1.34705680e+02, 9.80570194e+02, -5.63538495e+02, 1.65469425e+02, -9.18709377e+01, -1.44361222e+00,
				-1.28146257e+02, -3.94851363e+01, -2.71839432e+02, -1.82261009e+02, -2.40244372e+02, 9.22145060e+00,
				-8.69630894e+01, 4.48763793e+01, -5.18521140e+01, 2.05308881e+02, 1.90796460e+02, 1.24537182e+01,
				2.52770549e+01, 1.99144238e+01, 2.55476266e+01, 2.05348140e+01, 2.84093539e+01, -1.90796460e+02,
				-2.84093539e+01, -2.05348140e+01, -2.55476266e+01, -1.99144238e+01, -2.52770549e+01, -1.24537182e+01,
				1.82261009e+02, -2.05308881e+02, 5.18521140e+01, -4.48763793e+01, 8.69630894e+01, -9.22145060e+00,
				2.40244372e+02, 5.63538495e+02, 2.71839432e+02, 3.94851363e+01, 1.28146257e+02, 1.44361222e+00,
				9.18709377e+01, -1.65469425e+02, -1.14303074e+03, 1.15178226e+02, -1.57031248e+02, -6.95884427e+01,
				-1.99679753e+02, -1.14815474e+02, -3.50547174e+02, 3.83125174e+02, 2.58980088e+02, 1.98063681e+01,
				1.10201607e+02, -1.38602085e+01, 7.64474444e+01, -1.61487221e+02, -2.11202422e+02, 9.78194718e+01,
				-3.80131825e+01, 9.59459778e+00, -5.81102914e+01, -1.11725596e+01, -1.37526204e+02, -3.84933445e+01,
				-4.62797630e+01, 1.27629561e+00, -1.70780768e+01, 7.99699429e+00, -1.04421725e+01, 3.83134503e+01,
				-1.38122374e+00, 8.54175232e+01, -9.53290865e+00, 2.46588540e+01, -2.37162181e+01, 1.02741440e+01,
				-8.18271247e+01, -3.07050049e+02, -4.74460712e+01, -3.30388458e+01, -4.16729621e+01, -3.19641522e+01,
				-4.10869993e+01, -1.97658213e+01, 6.24901235e+01, -1.97994381e+02, 3.30352990e+01, -5.28963824e+01,
				6.53140996e+01, -2.01164325e+01, 2.03823613e+02, 5.94752652e+02, 5.63378498e+01, 7.85150677e+01,
				6.73449022e+01, 7.74506201e+01, 6.68891621e+01, 8.04551458e+01, -7.54660992e+01, -9.28269788e+01,
				1.81301928e+00, -3.34440288e+01, 1.67721287e+01, -1.88281014e+01, 8.06668084e+01, 1.33711551e+02,
				-2.16319281e+01, 2.21159887e+01, 5.23476360e+00, 2.78982127e+01, 1.10631040e+01, 5.41586228e+01,
				3.53035690e+01, 3.78298390e+01, 4.14748233e-01, 1.39323088e+01, -5.69528597e+00, 7.91435844e+00,
				-3.08034192e+01, 1.01729052e+01, -1.86639132e+01, 4.03126199e+00, -4.59412240e+00, 7.29416757e+00,
				-1.35573920e+00, 2.16863480e+01, 1.34648848e+02, 4.62702163e+01, 1.33930489e+01, 2.49316712e+01,
				7.27611530e+00, 1.90421719e+01, -1.70524510e+01, -8.18424760e+01, 1.22724317e+02, -2.72756801e+01,
				2.82612178e+01, -5.02921304e+01, 5.49032042e+00, -1.47983454e+02, -5.94752652e+02, -8.04551458e+01,
				-6.68891621e+01, -7.74506201e+01, -6.73449022e+01, -7.85150677e+01, -5.63378498e+01, 8.18424760e+01,
				1.47983454e+02, -5.49032042e+00, 5.02921304e+01, -2.82612178e+01, 2.72756801e+01, -1.22724317e+02,
				-1.34648848e+02, 1.70524510e+01, -1.90421719e+01, -7.27611530e+00, -2.49316712e+01, -1.33930489e+01,
				-4.62702163e+01, -1.01729052e+01, -2.16863480e+01, 1.35573920e+00, -7.29416757e+00, 4.59412240e+00,
				-4.03126199e+00, 1.86639132e+01, -3.53035690e+01, 3.08034192e+01, -7.91435844e+00, 5.69528597e+00,
				-1.39323088e+01, -4.14748233e-01, -3.78298390e+01, -1.33711551e+02, -5.41586228e+01, -1.10631040e+01,
				-2.78982127e+01, -5.23476360e+00, -2.21159887e+01, 2.16319281e+01, 7.54660992e+01, -8.06668084e+01,
				1.88281014e+01, -1.67721287e+01, 3.34440288e+01, -1.81301928e+00, 9.28269788e+01, 1.14303074e+03,
				3.50547174e+02, 1.14815474e+02, 1.99679753e+02, 6.95884427e+01, 1.57031248e+02, -1.15178226e+02,
				-6.24901235e+01, -2.03823613e+02, 2.01164325e+01, -6.53140996e+01, 5.28963824e+01, -3.30352990e+01,
				1.97994381e+02, 3.07050049e+02, 1.97658213e+01, 4.10869993e+01, 3.19641522e+01, 4.16729621e+01,
				3.30388458e+01, 4.74460712e+01, 1.38122374e+00, 8.18271247e+01, -1.02741440e+01, 2.37162181e+01,
				-2.46588540e+01, 9.53290865e+00, -8.54175232e+01, 3.84933445e+01, -3.83134503e+01, 1.04421725e+01,
				-7.99699429e+00, 1.70780768e+01, -1.27629561e+00, 4.62797630e+01, 2.11202422e+02, 1.37526204e+02,
				1.11725596e+01, 5.81102914e+01, -9.59459778e+00, 3.80131825e+01, -9.78194718e+01, -3.83125174e+02,
				1.61487221e+02, -7.64474444e+01, 1.38602085e+01, -1.10201607e+02, -1.98063681e+01, -2.58980088e+02,
				0.00000000e+00, -2.95214901e+03, 3.51414259e+02, -8.54538891e+02, 8.54538891e+02, -3.51414259e+02,
				2.95214901e+03, -1.82840526e+03, 1.65469425e+02, -2.67357962e+02, -1.14300043e+02, -3.31506517e+02,
				-1.80214803e+02, -5.88056124e+02, -5.71812813e+02, -7.31948087e+02, 9.22145060e+00, -2.62450114e+02,
				1.22975452e+02, -1.49240065e+02, 5.99624645e+02, 4.41318836e+02, -6.56453549e+01, 6.86187706e+01,
				1.99144238e+01, 8.81782204e+01, 3.98236921e+01, 1.69139021e+02, -4.41318836e+02, -1.69139021e+02,
				-3.98236921e+01, -8.81782204e+01, -1.99144238e+01, -6.86187706e+01, 6.56453549e+01, 5.71812813e+02,
				-5.99624645e+02, 1.49240065e+02, -1.22975452e+02, 2.62450114e+02, -9.22145060e+00, 7.31948087e+02,
				1.82840526e+03, 5.88056124e+02, 1.80214803e+02, 3.31506517e+02, 1.14300043e+02, 2.67357962e+02,
				-1.65469425e+02, -2.98964087e+03, -4.44244509e+02, -3.51739417e+02, -3.94461733e+02, -3.36458993e+02,
				-3.81759836e+02, -2.52776970e+02, 3.20400681e+02, 6.32818675e+02, -2.99869397e+01, 2.11600772e+02,
				-1.30940497e+02, 1.10559629e+02, -5.51006931e+02, -6.91057251e+02, 7.34359816e+01, -1.01907875e+02,
				-4.01987100e+01, -1.28280691e+02, -6.72415741e+01, -2.33106421e+02, -9.92187458e+01, -1.42483187e+02,
				3.42560274e+00, -5.00304530e+01, 2.57680201e+01, -2.77728299e+01, 1.19335524e+02, -1.45614083e+02,
				1.19529708e+02, -3.32931921e+01, 2.15530152e+01, -5.66685942e+01, -2.02378742e+00, -1.51997524e+02,
				-6.57054276e+02, -2.74464876e+02, -5.66452099e+01, -1.37876386e+02, -2.32617853e+01, -1.04981692e+02,
				1.19751927e+02, 4.21387885e+02, -4.82108528e+02, 1.14057372e+02, -1.02189917e+02, 2.04332075e+02,
				-1.14140656e+01, 5.77662200e+02, 1.03067817e+03, -2.17767931e+02, 1.69123854e+02, 2.77885665e+01,
				2.25988335e+02, 8.52617553e+01, 4.63542305e+02, -3.21235739e+02, -1.81078298e+02, -2.25846904e+01,
				-8.06308279e+01, 2.51651791e+00, -5.58728016e+01, 1.07475718e+02, 1.66737825e+02, -1.17172303e+02,
				3.71994796e+01, -1.91629461e+01, 6.05524908e+01, 4.23618159e+00, 1.57955566e+02, 1.01249339e+02,
				4.44510928e+01, 8.83625012e+00, 2.17113096e+01, 3.01215581e+00, 1.59792991e+01, -2.09382305e+01,
				-7.38878290e+00, -5.57086133e+01, 5.66657663e+00, -1.67635452e+01, 1.50731684e+01, -7.38147587e+00,
				5.43406261e+01, 2.97525723e+02, 1.86285716e+01, 3.90287768e+01, 3.15529250e+01, 4.13740803e+01,
				3.41256627e+01, 5.13084125e+01, 9.40101391e+01, 2.54938790e+02, -1.74104913e+01, 8.17923605e+01,
				-5.98601193e+01, 3.95882854e+01, -2.36234773e+02, -1.03067817e+03, -4.63542305e+02, -8.52617553e+01,
				-2.25988335e+02, -2.77885665e+01, -1.69123854e+02, 2.17767931e+02, -9.40101391e+01, 2.36234773e+02,
				-3.95882854e+01, 5.98601193e+01, -8.17923605e+01, 1.74104913e+01, -2.54938790e+02, -2.97525723e+02,
				-5.13084125e+01, -3.41256627e+01, -4.13740803e+01, -3.15529250e+01, -3.90287768e+01, -1.86285716e+01,
				7.38878290e+00, -5.43406261e+01, 7.38147587e+00, -1.50731684e+01, 1.67635452e+01, -5.66657663e+00,
				5.57086133e+01, -1.01249339e+02, 2.09382305e+01, -1.59792991e+01, -3.01215581e+00, -2.17113096e+01,
				-8.83625012e+00, -4.44510928e+01, -1.66737825e+02, -1.57955566e+02, -4.23618159e+00, -6.05524908e+01,
				1.91629461e+01, -3.71994796e+01, 1.17172303e+02, 3.21235739e+02, -1.07475718e+02, 5.58728016e+01,
				-2.51651791e+00, 8.06308279e+01, 2.25846904e+01, 1.81078298e+02, 2.98964087e+03, 2.52776970e+02,
				3.81759836e+02, 3.36458993e+02, 3.94461733e+02, 3.51739417e+02, 4.44244509e+02, -4.21387885e+02,
				-5.77662200e+02, 1.14140656e+01, -2.04332075e+02, 1.02189917e+02, -1.14057372e+02, 4.82108528e+02,
				6.57054276e+02, -1.19751927e+02, 1.04981692e+02, 2.32617853e+01, 1.37876386e+02, 5.66452099e+01,
				2.74464876e+02, 1.45614083e+02, 1.51997524e+02, 2.02378742e+00, 5.66685942e+01, -2.15530152e+01,
				3.32931921e+01, -1.19529708e+02, 9.92187458e+01, -1.19335524e+02, 2.77728299e+01, -2.57680201e+01,
				5.00304530e+01, -3.42560274e+00, 1.42483187e+02, 6.91057251e+02, 2.33106421e+02, 6.72415741e+01,
				1.28280691e+02, 4.01987100e+01, 1.01907875e+02, -7.34359816e+01, -3.20400681e+02, 5.51006931e+02,
				-1.10559629e+02, 1.30940497e+02, -2.11600772e+02, 2.99869397e+01, -6.32818675e+02 };
		f = FFT.fftn(b, new int[] { 5, 7, 7 }, null);
		assertEquals("3D double: rank", 4, f.getRank());
		assertEquals("3D double: shape", 2, f.getShape()[0]);
		assertEquals("3D double: shape", 5, f.getShape()[1]);
		assertEquals("3D double: shape", 7, f.getShape()[2]);
		assertEquals("3D double: shape", 7, f.getShape()[3]);
		i = 0;
		it = f.getIterator();
		while (it.hasNext()) {
			assertEquals("3D double: real", dr[i], f.getElementDoubleAbs(it.index),  Math.max(abstol,abstol*Math.abs(dr[i])));
			assertEquals("3D double: imag", di[i], f.getElementDoubleAbs(it.index+1), Math.max(abstol,abstol*Math.abs(di[i])));
			i++;
		}

		g = FFT.ifftn(f, null, new int[] { -3, -2, -1 });
		i = 0;
		it = g.getSliceIterator(null, b.getShape(), null);
		while (it.hasNext()) {
			assertEquals("3D double: real", i, g.getElementDoubleAbs(it.index), abstol);
			assertEquals("3D double: imag", 0, g.getElementDoubleAbs(it.index+1), abstol);
			i++;
		}
	}

	@Test
	public void testShift() {
		Dataset a;
		Dataset t;

		a = DatasetFactory.createRange(6, Dataset.FLOAT64);
		t = FFT.fftshift(a, null);
		TestUtils.assertDatasetEquals(DatasetFactory.createFromObject(new double[] {3, 4, 5, 0, 1, 2}), t, 1e-12, 1e-12);
		System.out.println(t.toString(true));
		t = FFT.ifftshift(t, null);
		System.out.println(t.toString(true));
		TestUtils.assertDatasetEquals(a, t, 1e-12, 1e-12);

		a.setShape(new int[] {3,2});
		System.out.println(a);

		t = FFT.fftshift(a, null);
		TestUtils.assertDatasetEquals(DatasetFactory.createFromObject(new double[] {5, 4, 1, 0, 3, 2}).reshape(3,2), t, 1e-12, 1e-12);
		System.out.println(t.toString(true));
		t = FFT.ifftshift(t, null);
		System.out.println(t.toString(true));
		TestUtils.assertDatasetEquals(a, t, 1e-12, 1e-12);

		t = FFT.fftshift(a, new int[] {0});
		TestUtils.assertDatasetEquals(DatasetFactory.createFromObject(new double[] {4, 5, 0, 1, 2, 3}).reshape(3,2), t, 1e-12, 1e-12);
		System.out.println(t.toString(true));
		t = FFT.ifftshift(t, new int[] {0});
		System.out.println(t.toString(true));
		TestUtils.assertDatasetEquals(a, t, 1e-12, 1e-12);

		t = FFT.fftshift(a, new int[] {1});
		TestUtils.assertDatasetEquals(DatasetFactory.createFromObject(new double[] {1, 0, 3, 2, 5, 4}).reshape(3,2), t, 1e-12, 1e-12);
		System.out.println(t.toString(true));
		t = FFT.ifftshift(t, new int[] {1});
		System.out.println(t.toString(true));
		TestUtils.assertDatasetEquals(a, t, 1e-12, 1e-12);

		t = FFT.fftshift(a, new int[] {1, 0});
		TestUtils.assertDatasetEquals(DatasetFactory.createFromObject(new double[] {5, 4, 1, 0, 3, 2}).reshape(3,2), t, 1e-12, 1e-12);
		System.out.println(t.toString(true));
		t = FFT.ifftshift(t, new int[] {1, 0});
		System.out.println(t.toString(true));
		TestUtils.assertDatasetEquals(a, t, 1e-12, 1e-12);

		a = DatasetFactory.createRange(7, Dataset.FLOAT64);
		t = FFT.fftshift(a, null);
		TestUtils.assertDatasetEquals(DatasetFactory.createFromObject(new double[] {4, 5, 6, 0, 1, 2, 3}), t, 1e-12, 1e-12);
		System.out.println(t.toString(true));
		t = FFT.ifftshift(t, null);
		System.out.println(t.toString(true));
		TestUtils.assertDatasetEquals(a, t, 1e-12, 1e-12);
	}

	@Test
	public void testFreq() {
		Dataset s, f;

		f = FFT.sampleFrequencies(6, 2.5);
		s = DatasetFactory.createFromObject(new double[] { 0, 0.06666667, 0.13333333, -0.2, -0.13333333, -0.06666667 });
		TestUtils.assertDatasetEquals(s, f, 1e-7, 1e-12);

		f = FFT.sampleFrequencies(7, 2.5);
		s = DatasetFactory.createFromObject(new double[] { 0, 0.05714286, 0.11428571, 0.17142857, -0.17142857, -0.11428571,
				-0.05714286 });
		TestUtils.assertDatasetEquals(s, f, 1e-7, 1e-12);
	}

	@Test
	public void testZeroPad() {
		Dataset w, z;
		w = DatasetFactory.createRange(DoubleDataset.class, 9).reshape(3, 3);
		z = FFT.zeroPad(w, new int[] {5, 5}, false);
		TestUtils.assertDatasetEquals(DatasetFactory.createFromObject(new double[] {
				0, 1, 2, 0, 0,
				3, 4, 5, 0, 0,
				6, 7, 8, 0, 0,
				0, 0, 0, 0, 0,
				0, 0, 0, 0, 0}).reshape(5, 5), z);

		z = FFT.zeroPad(w, new int[] {5, 5}, true);
		TestUtils.assertDatasetEquals(DatasetFactory.createFromObject(new double[] {
				0, 1, 0, 0, 2,
				3, 4, 0, 0, 5,
				0, 0, 0, 0, 0,
				0, 0, 0, 0, 0,
				6, 7, 0, 0, 8}).reshape(5, 5), z);
	}

	@Test
	public void testNewShift() {
		Dataset w, z;
		w = DatasetFactory.createRange(DoubleDataset.class, 35).reshape(5, 7);
		z = FFT.shift(w, true);
		TestUtils.assertDatasetEquals(DatasetFactory.createFromObject(new double[] {
				25, 26, 27, 21, 22, 23, 24,
				32, 33, 34, 28, 29, 30, 31,
				4, 5, 6, 0, 1, 2, 3,
				11, 12, 13, 7, 8, 9, 10,
				18, 19, 20, 14, 15, 16, 17}).reshape(5, 7), z);

		z = FFT.shift(z, false);
		TestUtils.assertDatasetEquals(w, z);

		z = FFT.shift(w, false);
		TestUtils.assertDatasetEquals(DatasetFactory.createFromObject(new double[] {
				17, 18, 19, 20, 14, 15, 16,
				24, 25, 26, 27, 21, 22, 23,
				31, 32, 33, 34, 28, 29, 30,
				3, 4, 5, 6, 0, 1, 2,
				10, 11, 12, 13, 7, 8, 9}).reshape(5, 7), z);
		z = FFT.shift(z, true);
		TestUtils.assertDatasetEquals(w, z);
	}
}
